////
/// @group menu
////

@use "sass:map";
@use "../utils";
@use "../spacing";
@use "../box-shadows";
@use "../theme/theme";
@use "../interaction/interaction";
@use "../icon/icon";
@use "../form/input-toggle";
@use "../form/switch";

/// Set to `true` to disable all the styles
/// @type Boolean
$disable-everything: false !default;

/// Set to `true` if the `MenuItem` component won't be used for some reason.
/// @type Boolean
$disable-menu-item: false !default;

/// Set to `true` to if the `MenuItemGroup` component will not be used.
/// @type Boolean
$disable-menu-item-group: false !default;

/// Set to `true` to disable the `MenuItemCheckbox` styles.
/// @type Boolean
$disable-menu-item-checkbox: $disable-menu-item or
  input-toggle.$disable-checkbox !default;

/// Set to `true` to disable the `MenuItemRadio` styles.
/// @type Boolean
$disable-menu-item-radio: $disable-menu-item or input-toggle.$disable-radio !default;

/// Set to `true` to disable the `MenuItemSwitch` styles.
/// @type Boolean
$disable-menu-item-switch: $disable-menu-item or
  switch.$disable-menu-item-switch !default;

/// Set to `true` to disable the dark mode elevation colors for the `Menu`.
/// @type Boolean
$disable-elevation-colors: theme.$disable-dark-elevation !default;

/// This should be a number between 0-24 representing the box-shadow elevation
/// of the `Menu`.
/// @type Number
$elevation: 8 !default;

/// The default background color to apply to a `Menu`.
/// @type Color
$background-color: theme.theme-get-var(surface-color) !default;

/// The default text color to apply to a `Menu`.
/// @type Color
$color: theme.theme-get-var(text-primary-color) !default;

/// The default `z-index` for a `Menu.
/// @type Number
$z-index: utils.$temporary-element-z-index !default;

/// The min width for a `Menu`.
/// @type Number
$min-width: 7rem !default;

/// The `gap` to apply to elements within the `MenuItem`.
/// @type Number
$spacing: spacing.get-var(md) !default;

/// The available configurable css variables and mostly used internally for the
/// `get-var`, `set-var`, and `use-var` utils.
/// @type List
$variables: (background-color, color, min-width, spacing);

/// @param {String} name - The supported variable name
/// @param {any} fallback [null] - An optional fallback value
/// @returns {String} a `var()` statement
@function get-var($name, $fallback: null) {
  $var: utils.get-var-name($variables, $name, "menu");
  @if $fallback {
    @return var(#{$var}, #{$fallback});
  }

  @return var(#{$var});
}

/// @param {String} name - The supported variable name
/// @param {any} value - The value to set the variable to. Supports `null` which
/// will just be a no-op.
@mixin set-var($name, $value) {
  @if $value {
    #{utils.get-var-name($variables, $name, "menu")}: #{$value};
  }
}

/// @param {String} property - The css property to apply the variable to
/// @param {String} name [$property] - The supported variable name
/// @param {any} fallback [null] - An optional fallback value if the variable
/// has not been set
@mixin use-var($property, $name: $property, $fallback: null) {
  #{$property}: get-var($name, $fallback);
}

/// Generates the `Menu` component styles.
///
/// NOTE: This should only be used if not using the `styles` mixin.
/// @see {mixin} styles
@mixin menu-styles {
  .rmd-menu {
    outline: none;
    overflow: auto;
    overflow-wrap: anywhere;

    &--elevated {
      @include box-shadows.box-shadow(
        $elevation,
        $disable-colors: $disable-elevation-colors
      );
      @if $disable-elevation-colors {
        @include use-var(
          background-color,
          $fallback: theme.theme-color-var-fallback($background-color)
        );
        @include use-var(
          color,
          $fallback: theme.theme-color-var-fallback($color)
        );
      }
      @include use-var(min-width);

      z-index: $z-index;
    }
  }
}

/// Generates the `MenuItem` component styles.
///
/// NOTE: This should only be used if not using the `styles` mixin.
/// @see {mixin} styles
@mixin menu-item-styles {
  .rmd-menu-item {
    @include icon.set-var(spacing, get-var(spacing));

    &--focused {
      // can't use `:focus-visible` here since this is mostly for virtual
      // keyboard movement for comboboxes. the focus is on the button or textbox
      // instead of a parent element
      @include utils.keyboard-only {
        @include interaction.set-var(
          background-color,
          interaction.get-var(focus-background-color)
        );

        &::before {
          @include interaction.focus-styles;
        }
      }
    }
  }
}

/// Generates the `MenuItemGroup` component styles.
///
/// NOTE: This should only be used if not using the `styles` mixin.
/// @see {mixin} styles
@mixin menu-item-group-styles {
  .rmd-menu-item-group {
    padding: 0;
  }
}

/// Generates the `MenuItemCheckbox`, `MenuItemRadio`, and `MenuItemSwitch` styles.
@mixin menu-item-input-toggle-styles($disable-layer: false) {
  .rmd-menu-item-input-toggle {
    @if not $disable-menu-item-radio or not $disable-menu-item-switch {
      &__icon {
        // remove the padding since the icon isn't the click target anymore.
        padding: 0;

        // disable the hover states since it's handled by the ListItem instead
        &::before {
          content: none;
        }
      }
    }

    @if not $disable-menu-item-switch {
      // this makes it so that the spacing between the switch and the text
      // aligns with other menu items/icons
      &__track {
        @include icon.set-var(size, switch.$track-width);
      }

      // decrease the ball size and remove the hover states since it's handled
      // by the ListItem instead. without decreasing the ball size, horizontal
      // scrollbars will appear when the switch is checked
      &__ball {
        height: switch.$ball-size;
        left: -#{switch.$ball-offset};
        top: calc(50% - switch.$ball-size * 0.5);
        width: switch.$ball-size;

        &::before {
          content: none;
        }

        &::after {
          inset: 0;
        }

        @include utils.rtl {
          left: auto;
          right: -#{switch.$ball-offset};
        }
      }
    }
  }
}

/// Conditionally applies the css variables based on feature flags
@mixin variables {
  @if not $disable-everything {
    @if not theme.is-theme-color-var($background-color) {
      @include set-var(background-color, $background-color);
    }
    @if not theme.is-theme-color-var($color) {
      @include set-var(color, $color);
    }
    @include set-var(min-width, $min-width);
    @include set-var(spacing, $spacing);
  }
}

/// Generates all the styles based on feature flags.
///
/// @param {Boolean} disable-layer [false] - Set this to `true` to disable the
/// layer behavior
@mixin styles($disable-layer: false) {
  @if not $disable-everything {
    @include utils.optional-layer(menu, $disable-layer) {
      @include menu-styles;

      @if not $disable-menu-item {
        @include menu-item-styles;
      }

      @if not $disable-menu-item-group {
        @include menu-item-group-styles;
      }

      @if not
        $disable-menu-item-checkbox or not
        $disable-menu-item-radio or not
        $disable-menu-item-switch
      {
        @include menu-item-input-toggle-styles;
      }
    }
  }
}
